/*
 * Copyright (C) 2010, Funcom AS, All Rights Reserved
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  @authors
 *  Svein Gunnar Larsen <sveingunnarlarsen@gmail.com>
 *  Erik Thune Lund <culex.eriklund@gmail.com>
 *  Michel Krohn-Dale <kronicz@gmail.com>
 */

package com.funcom.peeler.properties;

import com.funcom.peeler.PeelStyleSheet;
import com.funcom.peeler.WorkBench;
import com.funcom.peeler.adapter.KeyAndMouseAdapter;
import com.funcom.peeler.peelable.PeelComponent;
import com.funcom.peeler.peelable.PeelContainer;
import com.funcom.peeler.peelable.PeelLabel;
import com.funcom.peeler.peelable.PeelTextComponent;
import com.funcom.peeler.styleProperties.EffectColor;
import com.funcom.peeler.styleProperties.EffectSize;
import com.funcom.peeler.symbol.Symbol;
import com.funcom.peeler.utils.ColorPicker;
import com.jme.renderer.ColorRGBA;
import com.jmex.bui.BComponent;
import com.jmex.bui.Rule;
import com.jmex.bui.enumeratedConstants.TextEffect;
import com.jmex.bui.property.FontProperty;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Set;

import static java.awt.event.KeyEvent.VK_ENTER;

public class TextStyleProp extends UpdateableProperties {

    JList effectList;
    JTextField effectSize;
    JTextField fontSize;
    JTextField fontFamily;
    JComboBox fontStyle;
    JPanel pnlColor;
    JCheckBox[] stateBoxes;

    Color defaultColor = new Color(204, 204, 204);

    ColorRGBA colorRGBA;

    public TextStyleProp(JList effectList,
                         JTextField effectSize,
                         JTextField fontSize,
                         JTextField fontFamily,
                         JComboBox fontStyle,
                         JPanel pnlColor,
                         JCheckBox[] stateBoxes ) {

        this.effectList = effectList;
        this.effectSize = effectSize;
        this.fontSize   = fontSize;
        this.fontFamily = fontFamily;
        this.fontStyle  = fontStyle;
        this.pnlColor   = pnlColor;
        this.stateBoxes = stateBoxes;

        init();
        initListeners();
    }

    public void update() {
        fields_cleared = false;
    }

    public void needUpdate( WorkBench workBench,
                            Set<PeelComponent> allComp,
                            Set<PeelComponent> selectedComps,
                            PeelComponent main_selected,
                            PropertiesFrame thisFrame ) {

        if (main_selected == null) {
            selectedComp = null;
            if(!fields_cleared){
                clear();
                return;
            } else {
                return;
            }
        }

        if(main_selected != selectedComp){
            selectedComp = main_selected;

            if (selectedComp.getComponent().getName().equals("canvas_window")) return;

            String styleClass = selectedComp.getComponent().getStyleClass();
            PeelStyleSheet styleSheet = selectedComp.getStyleSheet();

            if(selectedComp instanceof PeelLabel){

                if (styleSheet == null) return;
                if (styleSheet.properties.get( styleClass ) == null) return;

                String effect = String.valueOf(styleSheet.properties.get(styleClass).properties.get(Symbol.StyleProperty.text_effect)).toLowerCase();
                if(!effect.equals("null")){
                    if(effect.equals("outline")) effectList.setSelectedIndex(1);
                    else if(effect.equals("shadow")) effectList.setSelectedIndex(2);
                    else if(effect.equals("plain")) effectList.setSelectedIndex(3);
                    else if(effect.equals("glow")) effectList.setSelectedIndex(4);
                }else{
                    effectList.setSelectedIndex(0);
                }

                String effect_size = String.valueOf(styleSheet.properties.get(styleClass).properties.get(Symbol.StyleProperty.effect_size));
                if(!effect_size.equals("null")) {
                    effectSize.setText(effect_size);
                }else effectSize.setText("");

                FontProperty font = (FontProperty) styleSheet.properties.get(styleClass).properties.get(Symbol.StyleProperty.font);

                if(font == null){
                    fontFamily.setText("");
                    fontSize.setText("");
                    fontStyle.setSelectedIndex(0);
                    wantUpdate = true;
                }else {
                    fontFamily.setText(font.family);
                    fontSize.setText(String.valueOf(font.size));
                    if(font.style.equals("plain")) fontStyle.setSelectedIndex(0);
                    else if(font.style.equals("bold")) fontStyle.setSelectedIndex(1);
                    else if(font.style.equals("italic")) fontStyle.setSelectedIndex(2);
                    else if(font.style.equals("bolditalic")) fontStyle.setSelectedIndex(3);
                }

                ColorRGBA background = (ColorRGBA) styleSheet.properties.get(styleClass).properties.get(Symbol.StyleProperty.effect_color);

                if( background == null) {
                    pnlColor.setBackground(defaultColor);
                    wantUpdate = true;
                    return;
                }else{
                    Color current_color = new Color(background.r, background.g, background.b);
                    if(!pnlColor.getBackground().equals(current_color)){
                        pnlColor.setBackground(current_color);
                    }
                }
            }else if(selectedComp instanceof PeelTextComponent || selectedComp instanceof PeelContainer){
                clear();
            }
            wantUpdate = true;
        }else{
            if(fields_cleared) {
                clear();
            }
        }

    }

    public void applyChange( PeelComponent component, PropertiesFrame updater) {

        switch(change) {

            case TEXT_EFFECT: {

                int effect = effectList.getSelectedIndex();
                updater.applyToSelectedStates(component, TextEffect.fromInt(effect));

                break;
            }

            case EFFECT_SIZE: {

                EffectSize newProp = new EffectSize();

                try {
                    newProp.size = Integer.parseInt(effectSize.getText());
                } catch (NumberFormatException e) {

                    SwingUtilities.invokeLater( new Runnable() {
                        public void run() {
                            effectSize.setText( String.valueOf( 0 ) );
                            JOptionPane.showMessageDialog(null, "Please insert a valid number ", "Invalid Input" , JOptionPane.WARNING_MESSAGE);
                        }
                    });
                }

                updater.applyToSelectedStates(component, newProp);

                break;
            }

            case EFFECT_COLOR: {

                EffectColor newProp = new EffectColor();

                newProp.colorRGBA = colorRGBA;

                updater.applyToSelectedStates(component, newProp);

                break;
            }

            case FONT: {

                FontProperty newFont = new FontProperty();

                try {
                    newFont.size = Integer.parseInt(fontSize.getText());
                } catch (NumberFormatException e) {

                    BComponent bComp = component.getComponent();
                    PeelStyleSheet stylesheet = component.getStyleSheet();
                    String pseudoClass = (String)stateBoxes[bComp.getState()].getClientProperty( "state" );
                    FontProperty prop = ((FontProperty)stylesheet.findPropertyObject( component, pseudoClass, Symbol.StyleProperty.font, true ));
                    newFont.size = prop == null ? 12 : prop.size;
                }
                newFont.family = fontFamily.getText();
                newFont.style  = (String)fontStyle.getSelectedItem();

                updater.applyToSelectedStates(component, newFont);

                break;
            }
        }
    }

    public void clear() {
        effectList.clearSelection();
        effectSize.setText("");
        pnlColor.setBackground(defaultColor);
        fontSize.setText("");
        fontFamily.setText("");
        fontStyle.setSelectedIndex(0);

        fields_cleared = true;
    }

    private void init() {

        this.pnlColor.setBackground(defaultColor);
        this.pnlColor.setBorder(BorderFactory.createEtchedBorder());

        effectList.setModel(new DefaultListModel());

        String optTextEffect[] = {"none", "outline", "shadow", "plain", "glow"};

        for (String anOptTextEffect : optTextEffect) {
            ((DefaultListModel) effectList.getModel()).addElement(anOptTextEffect);
        }
    }

    protected void initListeners() {

        TextStyleListener listener = new TextStyleListener();

        pnlColor.addMouseListener(listener);

        effectList.addKeyListener(listener);
        effectList.addMouseListener(listener);

        effectSize.addKeyListener(listener);
        effectSize.addMouseListener(listener);
        effectSize.addFocusListener( new FocusListener() {
            public void focusGained(FocusEvent e) {

            }
            public void focusLost(FocusEvent e) {
                change = ChangeProp.EFFECT_SIZE;
            }
        });


        fontSize.addKeyListener(listener);
        fontFamily.addKeyListener(listener);
        fontStyle.addItemListener( new ItemListener() {

            public void itemStateChanged(ItemEvent e) {
                change = ChangeProp.FONT;
            }
        });
    }

    private class TextStyleListener extends KeyAndMouseAdapter {
        public void keyPressed(KeyEvent e) {
            if (e.getSource() == effectList) {
                change = ChangeProp.TEXT_EFFECT;
            }
            if (e.getSource() == effectSize) {
                if (e.getKeyCode() == VK_ENTER) {
                    change = ChangeProp.EFFECT_SIZE;
                }
            }
            if (e.getSource() == fontSize ) {
                if (e.getKeyCode() == VK_ENTER) {
                    change = ChangeProp.FONT;
                }
            }
            if (e.getSource() == fontFamily) {
                if (e.getKeyCode() == VK_ENTER) {
                    change = ChangeProp.FONT;
                }
            }
        }
        public void mousePressed(MouseEvent e) {
            if (e.getSource() == effectList) {
                change = ChangeProp.TEXT_EFFECT;
            }

            if (e.getSource() == pnlColor) {

                colorRGBA = ColorPicker.selectColor(pnlColor, "Set text color");

                if (colorRGBA != null) {
                    change = ChangeProp.EFFECT_COLOR;
                }
            }
        }
    }
}
